package com.example.demo.config.logconfig.aop;

import java.util.Arrays;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.example.demo.Result;
import com.example.demo.config.consts.LogConst;
import com.example.demo.config.logconfig.LogBack;
import com.example.demo.zhoushengwen.utils.RequestUtil;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 
 * controller层日志切入
 * 
 * @author  huxing
 * @version  [版本号, 2020年3月19日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@Aspect
@Component
public class ControllerDigestAspect
{
    
    private long startTime = 0;
    
    @Autowired
    private HttpServletRequest request;
    
    @Autowired
    private HttpServletResponse response;
    
    @Autowired
    private MessageSource messageSource;
    
    /**
     * 设置切入点记录日志 扫描所有controller包下操作
     */
    @Pointcut("execution(public * com.example.demo.controller..*.*(..))")
    public void controllerLogPrint()
    {
    }
    
    @Before(value = "controllerLogPrint()")
    public void doBefore(JoinPoint joinPoint)
    {
        long begin = System.currentTimeMillis();
        startTime = begin;
        LogBack.info("CLIENTIP:{}|UUID:{}|position:{}|level:{}|status:{}|method:{}|param:{}|consume:{}",
            RequestUtil.getCliectIp(request),
            getUUID(),
            LogConst.LOG_CONTROLLER,
            LogConst.LOG_STATUS_INFO,
            LogConst.LOG_BEGIN,
            joinPoint.getSignature().toString(),
            Arrays.toString(joinPoint.getArgs()),
            0);
    }
    
    /**
     *返回通知
     *@param operation
     *@param returnValue
     */
    @AfterReturning(value = "controllerLogPrint()", returning = "returnValue")
    public void doAfterReturning(JoinPoint joinPoint, Object returnValue)
    {
        long end = System.currentTimeMillis();
        try
        {
            //demo只针对返回字段某一个提示信息进行映射
            String lang = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest()
                .getParameter("lang");
            Locale locale = new Locale(lang);
            String msg = messageSource.getMessage(((Result)returnValue).getMessage(), null, locale);
            ((Result)returnValue).setMessage(msg);
        }
        catch (Exception e)
        {
            //如果语言转换出问题，说明没有映射，捕捉异常不做处理
        }
        LogBack.info("CLIENTIP:{}|UUID:{}|position:{}|level:{}|status:{}|method:{}|param:{}|consume:{}",
            RequestUtil.getCliectIp(request),
            getUUID(),
            LogConst.LOG_CONTROLLER,
            LogConst.LOG_STATUS_INFO,
            LogConst.LOG_END,
            joinPoint.getSignature().toString(),
            returnValue,
            (end - startTime));
        
        response.setHeader(LogConst.HANDLE_RESULT, returnValue.toString());
    }
    
    /**
     * 异常通知
     * @param operation
     * @param e
     * @see [类、类#方法、类#成员]
     */
    @AfterThrowing(value = "controllerLogPrint()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e)
    {
        long end = System.currentTimeMillis();
        LogBack.info("CLIENTIP:{}|UUID:{}|position:{}|level:{}|status:{}|method:{}|param:{}|consume:{}|error:{}",
            RequestUtil.getCliectIp(request),
            getUUID(),
            LogConst.LOG_CONTROLLER,
            LogConst.LOG_STATUS_ERROR,
            LogConst.LOG_END,
            joinPoint.getSignature().toString(),
            Arrays.toString(joinPoint.getArgs()),
            (end - startTime),
            e);
    }
    
    private String getUUID()
    {
        if (null != request.getHeader(LogConst.LOG_UUID))
            return request.getHeader(LogConst.LOG_UUID);
        return response.getHeader(LogConst.LOG_UUID);
    }
}
